﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using FMSpaceShooter.GameService;
using FMSpaceShooter.Data;


namespace FMSpaceShooter.Screens
{
    class HighscoreMenuScreen : MenuScreen
    {
        enum HighscoreMenuScreenState { GetName, ShowLocal, ShowOnline };
        HighscoreMenuScreenState currentState = HighscoreMenuScreenState.GetName;

        SpriteFont scoreFont;

        Vector2 resolution;
        const string apiKey = "os7erh7p9AMva0s8d";
        UInt64 score;
        List<LocalScore> scores = new List<LocalScore>();
        List<Highscore> onlineScores = new List<Highscore>();
        string name = "";

        int localRank;
        long onlineIndex;

        public HighscoreMenuScreen(UInt64 score)
            : base("Game Over") 
        {
            this.score = score;

            List<string> MBOPTIONS = new List<string>();
            MBOPTIONS.Add("OK");
            Guide.BeginShowKeyboardInput(PlayerIndex.One, "Save Your Score", "Please Enter Your Name:", "", GetTypedChars, null);
        }

        public override void LoadContent()
        {
 	        base.LoadContent();
            ContentManager content = ScreenManager.Game.Content;
            scoreFont = content.Load<SpriteFont>("Fonts/ScoreFont");
        }

        protected void GetTypedChars(IAsyncResult r)
        {
            name = Guide.EndShowKeyboardInput(r);
            ShowLocalScores();
        }

        private void ShowLocalScores() 
        {
            MenuEntry submitMenuEntry = new MenuEntry("Submit Score Online");
            MenuEntry exitMenuEntry = new MenuEntry("Exit");

            exitMenuEntry.Selected += OnCancel;
            submitMenuEntry.Selected += OnSubmit;

            if (score > 0)
            {
                MenuEntries.Add(submitMenuEntry);
            }
            MenuEntries.Add(exitMenuEntry);


            LocalScore newScore = new LocalScore { date = DateTime.Now, name = name ?? "", score = score };
            HighscoreFile.AddScore(newScore);

            scores = HighscoreFile.GetHighscores().OrderByDescending(s => s.score).ToList();
            for (int i = 0; i < scores.Count; i++)
            {
                if (scores[i].Equals(newScore))
                {
                    localRank = i + 1;
                    break;
                }
            }

            this.menuTitle = "";
            currentState = HighscoreMenuScreenState.ShowLocal;
        }

        public void OnSubmit(object sender, EventArgs e)
        {
            try
            {
                MenuEntries.RemoveAt(0);

                using (GameInterfaceSoapClient gis = new GameInterfaceSoapClient())
                {
                    onlineIndex = gis.SubmitHighScore(apiKey, name, (long)score);

                    int page = (int)onlineIndex / 10;
                    onlineScores = gis.GetHighScores(page * 10, 10).ToList();
                    currentState = HighscoreMenuScreenState.ShowOnline;
                }
            }
            catch (Exception ex)
            {
                try {
                    Guide.BeginShowMessageBox("Error", "There was an error communicating with the server." + Environment.NewLine +
                        " Please try again later." + Environment.NewLine + ex.ToString()
                        , new List<string> { "OK" }, 0, MessageBoxIcon.Error, null, null);
                } catch (Exception) {
                }
            }
        }

        public override void Draw(GameTime gameTime)
        {

            resolution = new Vector2(((Game1)ScreenManager.Game).GDM.PreferredBackBufferWidth,
                ((Game1)ScreenManager.Game).GDM.PreferredBackBufferHeight);
            base.Draw(gameTime);

            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
            spriteBatch.Begin();

            if (currentState == HighscoreMenuScreenState.ShowLocal)
            {
                SpriteFont font = ScreenManager.Font;

                Vector2 location = new Vector2(resolution.X * .5f, resolution.Y * .25f);
                spriteBatch.DrawString(scoreFont, "Local Highscores", location, Color.White, 0,
                                       (scoreFont.MeasureString("Local Highscores") / 2), 1f, SpriteEffects.None, 0);

                int page = (localRank / 10);

                for (int i = page * 10; i < scores.Count && i < (page * 10) + 10; i++)
                {
                    var currentScore = scores[i];

                    string scoreText = string.Format("{0}  {1}{2}", 
                        (i+1).ToString().PadLeft(4), 
                        currentScore.name.ToString().PadRight(20, '.'), 
                        currentScore.score.ToString().PadLeft(21, '.'));

                    Vector2 scoreLocation = location + (new Vector2(0, 24 * ((i - page *10)+1)));
                    scoreLocation.X -= (float)(scoreFont.MeasureString(scoreText).X / 2);

                    spriteBatch.DrawString(scoreFont, scoreText, scoreLocation,
                        (localRank == (i + 1) ? Color.Yellow : Color.White), 
                                        0, Vector2.Zero, 1f, SpriteEffects.None, 0);
                }
            }
            else if (currentState == HighscoreMenuScreenState.ShowOnline)
            {
                SpriteFont font = ScreenManager.Font;

                Vector2 location = new Vector2(resolution.X * .5f, resolution.Y * .25f);
                spriteBatch.DrawString(scoreFont, "Online Highscores", location, Color.White, 0,
                                       (scoreFont.MeasureString("Online Highscores") / 2), 1f, SpriteEffects.None, 0);

                for (int i = 0; i < onlineScores.Count; i++)
                {
                    var currentScore = onlineScores[i];

                    string scoreText = string.Format("{0}  {1}{2}",
                        currentScore.rank.ToString().PadLeft(4),
                        currentScore.name.ToString().PadRight(20, '.'),
                        currentScore.highScore.ToString().PadLeft(21, '.'));

                    Vector2 scoreLocation = location + (new Vector2(0, 24 * (i + 1)));
                    scoreLocation.X -= (float)(scoreFont.MeasureString(scoreText).X / 2);

                    spriteBatch.DrawString(scoreFont, scoreText, scoreLocation,
                        (onlineIndex % 10 == (i + 1) ? Color.Yellow : Color.White),
                                        0, Vector2.Zero, 1f, SpriteEffects.None, 0);
                }
            }

            spriteBatch.End();
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
            if (currentState == HighscoreMenuScreenState.GetName)
            {
            }
        }

        public void Dispose()
        {
            throw new NotImplementedException();
        }
    }
}
